package base;

import java.net.Socket;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import model.*;

public class Controller {
	private Server server;
	private DatabaseConnection db = new DatabaseConnection("javauser");
	public static Map<User,Socket> userList = new HashMap<User,Socket>();
	public static Map<Group,List> groupList = new HashMap<Group,List>();
	public List<User> groupMemberBuff = new ArrayList<User>();
	public List<Socket> pushUserBuff = new ArrayList<Socket>();
	public static ArrayList<User> users;
	
	
	public Controller(Server server) throws SQLException{
		this.server = server;
		//db.prepare();
		//this.users = db.getUsers("\"1\" or \"1\"");
	}
	
	public void handleMessage(Socket socket)throws Exception{
		boolean isPush = false;
		Map<String,String> message = this.server.analyzeFromClient(socket);
		Map<String,String> response = new HashMap<String,String>();
		/*do something */
		String type = message.get("action");
		String status;
		if (!type.contains("/")){
			response.put("status", "Unknown operation.");
		}
		else{
			String front = type.substring(0, type.indexOf('/'));
			String behand = type.substring(type.indexOf('/')+1);
			switch(front){
			case "account":
				switch(behand){
				case "login":
					response = this.login(message, socket);
					break;
				case "logout":
					response = this.logout(message);
					break;
				case "register":
					response = this.register(message);
					break;
				default:
					response.put("status", "Unknown operation.");
					break;
				};
				break;
			case "group":
				switch(behand){
				case "create":
					response = this.create(message);
					break;
				case "join":
					response = this.join(message);
					break;
				case "quit":
					response = this.quit(message);
					break;
				default:
					response.put("status", "Unknown operation.");
					break;
				};
				break;
			default:
				response.put("status", "Unknown operation.");
				break;
			}
		}
		
		if (isPush){
			//pushUserBuff = this.getOnlineUserSockets();
			this.server.pushToClient(pushUserBuff, response);
			pushUserBuff = null;
		}else{
			this.server.sendToClient(socket, response);
		}
	}
	
	public Map<String,String> login(Map<String,String> message,Socket socket) throws SQLException{
		Map<String,String> response = new HashMap<String,String>();
		String status = "";
		String id = message.get("id");
		String password = message.get("password");
		User user = db.getUser(id);
		
		if (user!=null){
			if (user.getPassword().equals(password)){
				status = "ok";
				//this.updateOnlinegroups(user);
			}else{
				status = "This password is wrong";
			}
		}else{
			status = "This id is not exits.";
		}
		response.put("status",status);
		return response;
	}
	
	public Map<String,String> logout(Map<String,String> message) throws SQLException{
		Map<String,String> response = new HashMap<String,String>();
		String status = "";
		String id = message.get("id");
		User user = db.getUser(id);
		
		if(this.userList.containsKey(id)){
			this.userList.remove(user);
			status = "ok";
		}else{
			status = "This user is not logged.";
		}
		
		response.put("status",status);
		return response;
	}
	
	public Map<String,String> register(Map<String,String> message) throws SQLException{
		Map<String,String> response = new HashMap<String,String>();
		String status = "";
		String name = message.get("name");
		String password = message.get("password");
		String sex = message.get("sex");
		User user = new User();
		user.setId(db.getUUID(this));
		user.setName(name);
		user.setPassword(password);
		user.setSex(sex);
		String id = db.insertUser(user);
		status = "ok";
		response.put("status", status);
		response.put("id", id);
		return response;
	}
	
	public Map<String,String> join(Map<String,String> message) throws SQLException{
		Map<String,String> response = new HashMap<String,String>();
		String status = "";
		
		String userid = message.get("userid");
		String groupid = message.get("groupid");
		
		User user = db.getUser(userid);
		Group group = db.getGroup(groupid);
		
		if(user == null){
			response.put("status", "This user is not exits.");
		}else if(group == null){
			response.put("status", "This group is not exits.");
		}else{
			db.join(userid, groupid, "member");
			response.put("status", "ok");
		}
		return response;
	}
	
	public Map<String,String> create(Map<String,String> message) throws SQLException{
		Map<String,String> response = new HashMap<String,String>();
		String status = "";
		String groupid = db.getUUID(this);
		String name = message.get("name");
		String former = message.get("former");
		
		Group group = new Group();
		group.setId(groupid);
		group.setName(name);
		group.setFormer(former);
		
		db.insertGroup(group);
		
		List<User> members = db.getMembers(groupid);
		this.groupList.put(group,members);
		
		response.put("status", "ok");
		response.put("id", groupid);
		
		return response;
	}
	
	public Map<String,String> quit(Map<String,String> message) throws SQLException{
		Map<String,String> response = new HashMap<String,String>();
		String status = "";
		String userid = message.get("userid");
		String groupid = message.get("groupid");
		
		User user = db.getUser(userid);
		Group group = db.getGroup(groupid);
		
		if(user == null){
			response.put("status", "This user is not exits.");
		}else if(group == null){
			response.put("status", "This group is not exits.");
		}else{
			db.quit(userid, groupid);
			response.put("status", "ok");
		}
		
		return response;
	}
	
	private void updateOnlinegroups(Object obj) throws SQLException{
		if(obj instanceof User){
			User user = (User)obj;
			List<Group> updated = db.getCommunities(user.getId()); 
			ArrayList<User> members;
			List<Group> oldGroups = (List<Group>) this.groupList.keySet();
			if(!updated.isEmpty()){
				for(Group g:updated){
					if(!oldGroups.contains(g)){
						members = (ArrayList<User>) db.getMembers(g.getId());
						this.groupList.put(g, members);
						members = null;
					}else;
				}
			}
		}else if(obj instanceof Group){
			this.groupList.put((Group)obj,new ArrayList<User>());
		}else;
		
	}
	
	private void updateOnlineUsers(User user,Socket socket) throws SQLException {
		this.userList.put(user, socket);
		updateOnlinegroups(user);
	}
	
	/*
	public Map<String,String> onlineUser(Map<String,String> message) throws SQLException{
		Map<String,String> response = new HashMap<String,String>();
		String status = "";
		
		return response;
	}
	
	public List<Socket> getOnlineUserSockets(){
		List<Socket> users = new ArrayList<Socket>();
		users = (List<Socket>)this.userList.values();
		return users;
	}
	*/
	/*
	public Map<String,String> temp(Map<String,String> message) throws SQLException{
		Map<String,String> response = new HashMap<String,String>();
		String status = "";
		
		return response;
	}
	*/
}